using System;
using System.Collections.Generic;
using UnityEngine;

namespace FormicArch.Architecture.Module
{
    public abstract class BaseModule : IModule
    {
        protected readonly string moduleName;
        protected bool isInitialized;
        protected IModule parentModule;
        protected readonly List<IModule> childModules;
        protected readonly Dictionary<Type, IModule> moduleCache;

        public string Name => moduleName;
        public bool IsInitialized => isInitialized;

        protected BaseModule(string name)
        {
            moduleName = name;
            childModules = new List<IModule>();
            moduleCache = new Dictionary<Type, IModule>();
        }

        public virtual void Initialize()
        {
            if (isInitialized) return;

            foreach (var child in childModules)
            {
                child.Initialize();
            }

            isInitialized = true;
            Debug.Log($"Module {moduleName} initialized");
        }

        public virtual void Update()
        {
            if (!isInitialized) return;

            foreach (var child in childModules)
            {
                child.Update();
            }
        }

        public virtual void Dispose()
        {
            if (!isInitialized) return;

            foreach (var child in childModules)
            {
                child.Dispose();
            }

            isInitialized = false;
            Debug.Log($"Module {moduleName} disposed");
        }

        public IModule GetParentModule()
        {
            return parentModule;
        }

        public IReadOnlyList<IModule> GetChildModules()
        {
            return childModules.AsReadOnly();
        }

        public void AddChildModule(IModule module)
        {
            if (module == null) return;
            if (childModules.Contains(module)) return;

            childModules.Add(module);
            moduleCache.Clear(); // Clear cache when adding new module
        }

        public void RemoveChildModule(IModule module)
        {
            if (module == null) return;
            if (!childModules.Contains(module)) return;

            childModules.Remove(module);
            moduleCache.Clear(); // Clear cache when removing module
        }

        public T GetModule<T>() where T : IModule
        {
            var type = typeof(T);

            // Check cache first
            if (moduleCache.TryGetValue(type, out var cachedModule))
            {
                return (T)cachedModule;
            }

            // Check current module
            if (this is T currentModule)
            {
                moduleCache[type] = currentModule;
                return currentModule;
            }

            // Check child modules
            foreach (var child in childModules)
            {
                var found = child.GetModule<T>();
                if (found != null)
                {
                    moduleCache[type] = found;
                    return found;
                }
            }

            return default;
        }

        protected void SetParentModule(IModule parent)
        {
            parentModule = parent;
        }
    }
}